import abstract_decoder


class BrainfuckDecoder(abstract_decoder.AbstractDecoder):
    def __init__(self):
        super().__init__("Brainfuck")

    def is_valid(self, data, key=None):
        # 简单判断是否为 Brainfuck 代码
        return all(c in "><+-.,[] \r\n" for c in data)
    

    def decode(self, data):
        # 去除空格和注释
        # data = self.clear(data)
        brainfuck_code = "".join(data.split())
        brainfuck_code = "".join(filter(lambda x: x in "><+-.,[]", brainfuck_code))
        # print(brainfuck_code)
        # Brainfuck 解释器
        tape = [0] * 30000  # 30,000 字节的磁带（Brainfuck 标准）
        ptr = 0  # 指针
        output = []

        loop_stack = []
        loop_map = {}

        # 预处理循环匹配
        for i, cmd in enumerate(brainfuck_code):
            if cmd == "[":
                loop_stack.append(i)
            elif cmd == "]":
                if not loop_stack:
                    raise ValueError("Unmatched ']'")
                start = loop_stack.pop()
                loop_map[start] = i
                loop_map[i] = start

        i = 0
        while i < len(brainfuck_code):
            cmd = brainfuck_code[i]

            if cmd == ">":
                ptr += 1
                if ptr >= len(tape):
                    tape.append(0)
            elif cmd == "<":
                ptr -= 1
                if ptr < 0:
                    raise ValueError("Pointer moved below 0")
            elif cmd == "+":
                tape[ptr] = (tape[ptr] + 1) % 256
            elif cmd == "-":
                tape[ptr] = (tape[ptr] - 1) % 256
            elif cmd == ".":
                output.append(chr(tape[ptr]))
            elif cmd == ",":
                # 输入功能（这里不处理）
                pass
            elif cmd == "[":
                if tape[ptr] == 0:
                    i = loop_map[i]
            elif cmd == "]":
                if tape[ptr] != 0:
                    i = loop_map[i]
            i += 1

        return "".join(output)


if __name__ == "__main__":
    decoder = BrainfuckDecoder()
    with open("test-data/bugku_brainfuck.txt", "r") as f:
        data = f.read()
    if decoder.is_valid(data):
        print(decoder.decode(data))
